home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 2000 October / Software of the Month - Ultimate Collection Shareware 277.iso / pc / PROGRAMS / UTILITY / WINLINUX / DATA1.CAB / programs_-_include / ASM-SPAR.{_A / BITOPS.H < prev    next >
C/C++ Source or Header  |  1999-09-17  |  9KB  |  393 lines

  1. /* $Id: bitops.h,v 1.26 1999/01/07 14:14:15 jj Exp $
  2.  * bitops.h: Bit string operations on the V9.
  3.  *
  4.  * Copyright 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
  5.  */
  6.  
  7. #ifndef _SPARC64_BITOPS_H
  8. #define _SPARC64_BITOPS_H
  9.  
  10. #include <asm/byteorder.h>
  11. #include <asm/asi.h>         /* For the little endian spaces. */
  12.  
  13. /* These can all be exported to userland, because the atomic
  14.  * primitives used are not privileged.
  15.  */
  16.  
  17. /* Set bit 'nr' in 64-bit quantity at address 'addr' where bit '0'
  18.  * is in the highest of the eight bytes and bit '63' is the high bit
  19.  * within the first byte. Sparc is BIG-Endian. Unless noted otherwise
  20.  * all bit-ops return 0 if bit was previously clear and != 0 otherwise.
  21.  */
  22.  
  23. extern __inline__ unsigned long test_and_set_bit(unsigned long nr, void *addr)
  24. {
  25.     unsigned long * m = ((unsigned long *) addr) + (nr >> 6);
  26.     unsigned long oldbit;
  27.  
  28.     __asm__ __volatile__("
  29. 1:    ldx        [%2], %%g7
  30.     andcc        %%g7, %1, %0
  31.     bne,pn        %%xcc, 2f
  32.      xor        %%g7, %1, %%g5
  33.     casx         [%2], %%g7, %%g5
  34.     cmp        %%g7, %%g5
  35.     bne,pn        %%xcc, 1b
  36.      nop
  37. 2:
  38. "    : "=&r" (oldbit)
  39.     : "HIr" (1UL << (nr & 63)), "r" (m)
  40.     : "g5", "g7", "cc", "memory");
  41.     return oldbit != 0;
  42. }
  43.  
  44. extern __inline__ void set_bit(unsigned long nr, void *addr)
  45. {
  46.     unsigned long * m = ((unsigned long *) addr) + (nr >> 6);
  47.  
  48.     __asm__ __volatile__("
  49. 1:    ldx        [%1], %%g7
  50.     andcc        %%g7, %0, %%g0
  51.     bne,pn        %%xcc, 2f
  52.      xor        %%g7, %0, %%g5
  53.     casx         [%1], %%g7, %%g5
  54.     cmp        %%g7, %%g5
  55.     bne,pn        %%xcc, 1b
  56.      nop
  57. 2:
  58. "    : /* no outputs */
  59.     : "HIr" (1UL << (nr & 63)), "r" (m)
  60.     : "g5", "g7", "cc", "memory");
  61. }
  62.  
  63. extern __inline__ unsigned long test_and_clear_bit(unsigned long nr, void *addr)
  64. {
  65.     unsigned long * m = ((unsigned long *) addr) + (nr >> 6);
  66.     unsigned long oldbit;
  67.  
  68.     __asm__ __volatile__("
  69. 1:    ldx        [%2], %%g7
  70.     andcc        %%g7, %1, %0
  71.     be,pn        %%xcc, 2f
  72.      xor        %%g7, %1, %%g5
  73.     casx         [%2], %%g7, %%g5
  74.     cmp        %%g7, %%g5
  75.     bne,pn        %%xcc, 1b
  76.      nop
  77. 2:
  78. "    : "=&r" (oldbit)
  79.     : "HIr" (1UL << (nr & 63)), "r" (m)
  80.     : "g5", "g7", "cc", "memory");
  81.     return oldbit != 0;
  82. }
  83.  
  84. extern __inline__ void clear_bit(unsigned long nr, void *addr)
  85. {
  86.     unsigned long * m = ((unsigned long *) addr) + (nr >> 6);
  87.  
  88.     __asm__ __volatile__("
  89. 1:    ldx        [%1], %%g7
  90.     andcc        %%g7, %0, %%g0
  91.     be,pn        %%xcc, 2f
  92.      xor        %%g7, %0, %%g5
  93.     casx         [%1], %%g7, %%g5
  94.     cmp        %%g7, %%g5
  95.     bne,pn        %%xcc, 1b
  96.      nop
  97. 2:
  98. "    : /* no outputs */
  99.     : "HIr" (1UL << (nr & 63)), "r" (m)
  100.     : "g5", "g7", "cc", "memory");
  101. }
  102.  
  103. extern __inline__ unsigned long test_and_change_bit(unsigned long nr, void *addr)
  104. {
  105.     unsigned long * m = ((unsigned long *) addr) + (nr >> 6);
  106.     unsigned long oldbit;
  107.  
  108.     __asm__ __volatile__("
  109. 1:    ldx        [%2], %%g7
  110.     and        %%g7, %1, %0
  111.     xor        %%g7, %1, %%g5
  112.     casx         [%2], %%g7, %%g5
  113.     cmp        %%g7, %%g5
  114.     bne,pn        %%xcc, 1b
  115.      nop
  116. "    : "=&r" (oldbit)
  117.     : "HIr" (1UL << (nr & 63)), "r" (m)
  118.     : "g5", "g7", "cc", "memory");
  119.     return oldbit != 0;
  120. }
  121.  
  122. extern __inline__ void change_bit(unsigned long nr, void *addr)
  123. {
  124.     unsigned long * m = ((unsigned long *) addr) + (nr >> 6);
  125.  
  126.     __asm__ __volatile__("
  127. 1:    ldx        [%1], %%g7
  128.     xor        %%g7, %0, %%g5
  129.     casx         [%1], %%g7, %%g5
  130.     cmp        %%g7, %%g5
  131.     bne,pn        %%xcc, 1b
  132.      nop
  133. "    : /* no outputs */
  134.     : "HIr" (1UL << (nr & 63)), "r" (m)
  135.     : "g5", "g7", "cc", "memory");
  136. }
  137.  
  138. extern __inline__ unsigned long test_bit(int nr, __const__ void *addr)
  139. {
  140.     return 1UL & (((__const__ long *) addr)[nr >> 6] >> (nr & 63));
  141. }
  142.  
  143. /* The easy/cheese version for now. */
  144. extern __inline__ unsigned long ffz(unsigned long word)
  145. {
  146.     unsigned long result;
  147.  
  148. #ifdef ULTRA_HAS_POPULATION_COUNT    /* Thanks for nothing Sun... */
  149.     __asm__ __volatile__("
  150.     brz,pn    %0, 1f
  151.      neg    %0, %%g1
  152.     xnor    %0, %%g1, %%g2
  153.     popc    %%g2, %0
  154. 1:    " : "=&r" (result)
  155.       : "0" (word)
  156.       : "g1", "g2");
  157. #else
  158. #if 1 /* def EASY_CHEESE_VERSION */
  159.     result = 0;
  160.     while(word & 1) {
  161.         result++;
  162.         word >>= 1;
  163.     }
  164. #else
  165.     unsigned long tmp;
  166.  
  167.     result = 0;    
  168.     tmp = ~word & -~word;
  169.     if (!(unsigned)tmp) {
  170.         tmp >>= 32;
  171.         result = 32;
  172.     }
  173.     if (!(unsigned short)tmp) {
  174.         tmp >>= 16;
  175.         result += 16;
  176.     }
  177.     if (!(unsigned char)tmp) {
  178.         tmp >>= 8;
  179.         result += 8;
  180.     }
  181.     if (tmp & 0xf0) result += 4;
  182.     if (tmp & 0xcc) result += 2;
  183.     if (tmp & 0xaa) result ++;
  184. #endif
  185. #endif
  186.     return result;
  187. }
  188.  
  189. #ifdef __KERNEL__
  190.  
  191. /*
  192.  * ffs: find first bit set. This is defined the same way as
  193.  * the libc and compiler builtin ffs routines, therefore
  194.  * differs in spirit from the above ffz (man ffs).
  195.  */
  196.  
  197. #define ffs(x) generic_ffs(x)
  198.  
  199. /*
  200.  * hweightN: returns the hamming weight (i.e. the number
  201.  * of bits set) of a N-bit word
  202.  */
  203.  
  204. #ifdef ULTRA_HAS_POPULATION_COUNT
  205.  
  206. extern __inline__ unsigned int hweight32(unsigned int w)
  207. {
  208.     unsigned int res;
  209.  
  210.     __asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xffffffff));
  211.     return res;
  212. }
  213.  
  214. extern __inline__ unsigned int hweight16(unsigned int w)
  215. {
  216.     unsigned int res;
  217.  
  218.     __asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xffff));
  219.     return res;
  220. }
  221.  
  222. extern __inline__ unsigned int hweight8(unsigned int w)
  223. {
  224.     unsigned int res;
  225.  
  226.     __asm__ ("popc %1,%0" : "=r" (res) : "r" (w & 0xff));
  227.     return res;
  228. }
  229.  
  230. #else
  231.  
  232. #define hweight32(x) generic_hweight32(x)
  233. #define hweight16(x) generic_hweight16(x)
  234. #define hweight8(x) generic_hweight8(x)
  235.  
  236. #endif
  237. #endif /* __KERNEL__ */
  238.  
  239. /* find_next_zero_bit() finds the first zero bit in a bit string of length
  240.  * 'size' bits, starting the search at bit 'offset'. This is largely based
  241.  * on Linus's ALPHA routines, which are pretty portable BTW.
  242.  */
  243.  
  244. extern __inline__ unsigned long find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
  245. {
  246.     unsigned long *p = ((unsigned long *) addr) + (offset >> 6);
  247.     unsigned long result = offset & ~63UL;
  248.     unsigned long tmp;
  249.  
  250.     if (offset >= size)
  251.         return size;
  252.     size -= result;
  253.     offset &= 63UL;
  254.     if (offset) {
  255.         tmp = *(p++);
  256.         tmp |= ~0UL >> (64-offset);
  257.         if (size < 64)
  258.             goto found_first;
  259.         if (~tmp)
  260.             goto found_middle;
  261.         size -= 64;
  262.         result += 64;
  263.     }
  264.     while (size & ~63UL) {
  265.         if (~(tmp = *(p++)))
  266.             goto found_middle;
  267.         result += 64;
  268.         size -= 64;
  269.     }
  270.     if (!size)
  271.         return result;
  272.     tmp = *p;
  273.  
  274. found_first:
  275.     tmp |= ~0UL << size;
  276. found_middle:
  277.     return result + ffz(tmp);
  278. }
  279.  
  280. #define find_first_zero_bit(addr, size) \
  281.         find_next_zero_bit((addr), (size), 0)
  282.  
  283. /* Now for the ext2 filesystem bit operations and helper routines.
  284.  * Note the usage of the little endian ASI's, werd, V9 is supreme.
  285.  */
  286. extern __inline__ int set_le_bit(int nr,void * addr)
  287. {
  288.     unsigned int * m = ((unsigned int *) addr) + (nr >> 5);
  289.     unsigned long oldbit;
  290.  
  291.     __asm__ __volatile__("
  292. 1:    lduwa        [%2] %3, %%g7
  293.     andcc        %%g7, %1, %0
  294.     bne,pn        %%icc, 2f
  295.      xor        %%g7, %1, %%g5
  296.     casa         [%2] %3, %%g7, %%g5
  297.     cmp        %%g7, %%g5
  298.     bne,pn        %%icc, 1b
  299.      nop
  300. 2:
  301. "    : "=&r" (oldbit)
  302.     : "HIr" (1UL << (nr & 31)), "r" (m), "i" (ASI_PL)
  303.     : "g5", "g7", "cc", "memory");
  304.     return oldbit != 0;
  305. }
  306.  
  307. extern __inline__ int clear_le_bit(int nr, void * addr)
  308. {
  309.     unsigned int * m = ((unsigned int *) addr) + (nr >> 5);
  310.     unsigned long oldbit;
  311.  
  312.     __asm__ __volatile__("
  313. 1:    lduwa        [%2] %3, %%g7
  314.     andcc        %%g7, %1, %0
  315.     be,pn        %%icc, 2f
  316.      xor        %%g7, %1, %%g5
  317.     casa         [%2] %3, %%g7, %%g5
  318.     cmp        %%g7, %%g5
  319.     bne,pn        %%icc, 1b
  320.      nop
  321. 2:
  322. "    : "=&r" (oldbit)
  323.     : "HIr" (1UL << (nr & 31)), "r" (m), "i" (ASI_PL)
  324.     : "g5", "g7", "cc", "memory");
  325.     return oldbit != 0;
  326. }
  327.  
  328. extern __inline__ int test_le_bit(int nr, __const__ void * addr)
  329. {
  330.     int            mask;
  331.     __const__ unsigned char    *ADDR = (__const__ unsigned char *) addr;
  332.  
  333.     ADDR += nr >> 3;
  334.     mask = 1 << (nr & 0x07);
  335.     return ((mask & *ADDR) != 0);
  336. }
  337.  
  338. #define find_first_zero_le_bit(addr, size) \
  339.         find_next_zero_le_bit((addr), (size), 0)
  340.  
  341. extern __inline__ unsigned long find_next_zero_le_bit(void *addr, unsigned long size, unsigned long offset)
  342. {
  343.     unsigned long *p = ((unsigned long *) addr) + (offset >> 6);
  344.     unsigned long result = offset & ~63UL;
  345.     unsigned long tmp;
  346.  
  347.     if (offset >= size)
  348.         return size;
  349.     size -= result;
  350.     offset &= 63UL;
  351.     if(offset) {
  352.         tmp = __swab64p(p++);
  353.         tmp |= (~0UL >> (64-offset));
  354.         if(size < 64)
  355.             goto found_first;
  356.         if(~tmp)
  357.             goto found_middle;
  358.         size -= 64;
  359.         result += 64;
  360.     }
  361.     while(size & ~63) {
  362.         if(~(tmp = __swab64p(p++)))
  363.             goto found_middle;
  364.         result += 64;
  365.         size -= 64;
  366.     }
  367.     if(!size)
  368.         return result;
  369.     tmp = __swab64p(p);
  370. found_first:
  371.     tmp |= (~0UL << size);
  372. found_middle:
  373.     return result + ffz(tmp);
  374. }
  375.  
  376. #ifdef __KERNEL__
  377.  
  378. #define ext2_set_bit            set_le_bit
  379. #define ext2_clear_bit            clear_le_bit
  380. #define ext2_test_bit              test_le_bit
  381. #define ext2_find_first_zero_bit    find_first_zero_le_bit
  382. #define ext2_find_next_zero_bit        find_next_zero_le_bit
  383.  
  384. /* Bitmap functions for the minix filesystem.  */
  385. #define minix_set_bit(nr,addr) test_and_set_bit(nr,addr)
  386. #define minix_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
  387. #define minix_test_bit(nr,addr) test_bit(nr,addr)
  388. #define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
  389.  
  390. #endif /* __KERNEL__ */
  391.  
  392. #endif /* defined(_SPARC64_BITOPS_H) */
  393.